package cn.itcast.bos.service.take_delivery.impl;

import java.util.List;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryStringQueryBuilder;
import org.elasticsearch.index.query.QueryStringQueryBuilder.Operator;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.index.query.WildcardQueryBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cn.itcast.bos.dao.take_delivery.WayBillRepository;
import cn.itcast.bos.domain.take_delivery.WayBill;
import cn.itcast.bos.index.WayBillIndexRepository;
import cn.itcast.bos.service.take_delivery.WayBillService;

@Transactional
@Service
public class WayBillServiceimpl implements WayBillService{

	@Autowired
	private WayBillRepository wayBillRepository;
	
	@Autowired
	private WayBillIndexRepository wayBillIndexRepository;
	
	@SuppressWarnings("all")
	@Override
	public void save(WayBill wayBill) {
//		通过运单号查询运单对象。 以为前台在录入运单信息的时候 没有运单主键的id 所以无法做修改操作
		WayBill persistWayBill = wayBillRepository.findByWayBillNum(wayBill.getWayBillNum());
//		如果运单号或者运单号id不存在 执行保存操作  
        if(persistWayBill==null ||  persistWayBill.getId()  == null){
        	//如果运单号不存在
        	wayBill.setSignStatus(1);  //待发货
        	//保存到数据库        	 		
        	wayBillRepository.save(wayBill);
        	// 保存订单的同时 把数据保存到索引库       	
        	wayBillIndexRepository.save(wayBill);
        }else{        	
        	try {
        	  //判断运单号状态是否是待发货状态  待发货就保存
              if(persistWayBill.getSignStatus() ==1){
            	  //copyPeoperties方法会把瞬时态对象persistWayBil的id丢失 所以要先保存 copy完之后再复制进去
          		Integer  wayBillId = persistWayBill.getId();
          		//把前台传过来的瞬时态对象的值copy复制给数据库查询出啦爱的持久化对象persistWayBil 
          		//然后session关闭时hibernate具有自动更新的能力
  				BeanUtils.copyProperties(persistWayBill, wayBill);
  				persistWayBill.setId(wayBillId);		
  				persistWayBill.setSignStatus(1);
  				// 保存运单的同时 把数据保存到索引库中
  				wayBillIndexRepository.save(persistWayBill);
              }else{
            	 throw new RuntimeException("订单已发出 无法修改保存");
              }
				
			} catch (Exception e) {
				e.printStackTrace();
				throw new RuntimeException("wayBillServiceimpl抛出异常"+e.getMessage());
			}  
        }
		
	}
  
	
	//无条件分页查询
	@Override
	public Page<WayBill> findPageDate(WayBill wayBill,Pageable pageable) {
		//判断waybill中条件是否存在   不存在就是去数据库查询数据 
		if(StringUtils.isBlank(wayBill.getWayBillNum())   //订单号
				&&StringUtils.isBlank(wayBill.getSendAddress()) //发货地址
				&&StringUtils.isBlank(wayBill.getRecAddress())  //收货地址
				&&StringUtils.isBlank(wayBill.getSendProNum())  //速运类型
				&&(wayBill.getSignStatus() == null  || wayBill.getSignStatus()==0)){   //订单状态
			    System.out.println("查询的发货地址"+wayBill.getSendAddress());
			    System.out.println("无条件查询 正在查询数据库");
			    return wayBillRepository.findAll(pageable);
				} else {
					// 查询条件
					// must 条件必须成立 and   must not 条件必须不成立 not     should 条件可以成立 or
					//如果有查询条件 去索引库中查找数据    BoolQueryBuilder 为组合条件查询
					BoolQueryBuilder query = new BoolQueryBuilder(); // 布尔查询 ，多条件组合查询
					// 向组合查询对象添加条件
					//must  not 表示条件必须不成立了  相当于not   should 表示条件可以不成立 相当or
					if (StringUtils.isNoneBlank(wayBill.getWayBillNum())) {
						// 运单号查询  等值匹配
						QueryBuilder queryBuilder = new TermQueryBuilder("wayBillNum",wayBill.getWayBillNum());
						query.must(queryBuilder);
					}
					if (StringUtils.isNoneBlank(wayBill.getSendAddress())) {
						// 发货地 模糊查询
						// 情况一： 输入"北" 是查询词条一部分， 使用模糊匹配词条查询
						QueryBuilder wildcardQuery = new WildcardQueryBuilder(
								"sendAddress", "*" + wayBill.getSendAddress() + "*");
						System.out.println("词条匹配"+wildcardQuery);
						// 情况二： 输入"北京市海淀区" 是多个词条组合，进行分词后 每个词条匹配查询
						QueryBuilder queryStringQueryBuilder = new QueryStringQueryBuilder(
								wayBill.getSendAddress()).field("sendAddress").defaultOperator(Operator.AND);
						System.out.println("多词条匹配"+queryStringQueryBuilder);
						// 两种情况取or关系						 
						BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
						boolQueryBuilder.should(wildcardQuery);
						boolQueryBuilder.should(queryStringQueryBuilder);
						query.must(boolQueryBuilder);
					}
					
					//模糊查询  收货地址
					if (StringUtils.isNoneBlank(wayBill.getRecAddress())) {
						System.out.println("收货地址"+wayBill.getRecAddress());
						// 收货地 模糊查询
						QueryBuilder wildcardQuery = new WildcardQueryBuilder(
								"recAddress", "*" + wayBill.getRecAddress() + "*");
						query.must(wildcardQuery);
					}
					
					
					//快递类型 等值查询
					if (StringUtils.isNoneBlank(wayBill.getSendProNum())) {
						// 速运类型 等值查询
						QueryBuilder termQuery = new TermQueryBuilder("sendProNum",wayBill.getSendProNum());
						query.must(termQuery);
					}
					
					//前台默认提交的wayBill.getSignStatus()是0，但是索引库中的订单状态码为null，所以注意这里是&&。
					//如果是||name就一直会进来，然后携带条件SignStatus=0，一致查不到  
					if (wayBill.getSignStatus() != null && wayBill.getSignStatus() != 0) {
						// 签收状态查询
						QueryBuilder termQuery = new TermQueryBuilder("signStatus",wayBill.getSignStatus());
						query.must(termQuery);
					}
					//将组合条件查询传入NativeSearchQuery
					SearchQuery searchQuery = new NativeSearchQuery(query);
					searchQuery.setPageable(pageable); // 分页效果
					// 有条件查询 、查询索引库
					System.out.println("查询索引库"+searchQuery.toString());
					return wayBillIndexRepository.search(searchQuery);
				}
    		 
	}

	//根据运单回显表单数据
	@Override
	public WayBill findByWayBillNum(String wayBillNum) {
		// TODO Auto-generated method stub
		return wayBillRepository.findByWayBillNum(wayBillNum);
	}


	@Override
	public void syncIndex() {
		//查询数据库
	    List<WayBill> wayBills = wayBillRepository.findAll();
	    //同步索引库
	    wayBillIndexRepository.save(wayBills);
	}


	
	
	//查询数据生成报表
	@Override
	public List<WayBill> findByWayBills(WayBill wayBill) {
		//判断waybill中条件是否存在   不存在就是去数据库查询数据 
		if(StringUtils.isBlank(wayBill.getWayBillNum())   //订单号
				&&StringUtils.isBlank(wayBill.getSendAddress()) //发货地址
				&&StringUtils.isBlank(wayBill.getRecAddress())  //收货地址
				&&StringUtils.isBlank(wayBill.getSendProNum())  //速运类型
				&&(wayBill.getSignStatus() == null  || wayBill.getSignStatus()==0)){   //订单状态
			    System.out.println("查询的发货地址"+wayBill.getSendAddress());
			    System.out.println("无条件查询 正在查询数据库");
			      return wayBillRepository.findAll();
				} else {
					// 查询条件
					// must 条件必须成立 and   must not 条件必须不成立 not     should 条件可以成立 or
					//如果有查询条件 去索引库中查找数据    BoolQueryBuilder 为组合条件查询
					BoolQueryBuilder query = new BoolQueryBuilder(); // 布尔查询 ，多条件组合查询
					// 向组合查询对象添加条件
					//must  not 表示条件必须不成立了  相当于not   should 表示条件可以不成立 相当or
					if (StringUtils.isNoneBlank(wayBill.getWayBillNum())) {
						// 运单号查询  等值匹配
						QueryBuilder queryBuilder = new TermQueryBuilder("wayBillNum",wayBill.getWayBillNum());
						query.must(queryBuilder);
					}
					if (StringUtils.isNoneBlank(wayBill.getSendAddress())) {
						// 发货地 模糊查询
						// 情况一： 输入"北" 是查询词条一部分， 使用模糊匹配词条查询
						QueryBuilder wildcardQuery = new WildcardQueryBuilder(
								"sendAddress", "*" + wayBill.getSendAddress() + "*");
						System.out.println("词条匹配"+wildcardQuery);
						// 情况二： 输入"北京市海淀区" 是多个词条组合，进行分词后 每个词条匹配查询
						QueryBuilder queryStringQueryBuilder = new QueryStringQueryBuilder(
								wayBill.getSendAddress()).field("sendAddress").defaultOperator(Operator.AND);
						System.out.println("多词条匹配"+queryStringQueryBuilder);
						// 两种情况取or关系						 
						BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
						boolQueryBuilder.should(wildcardQuery);
						boolQueryBuilder.should(queryStringQueryBuilder);
						query.must(boolQueryBuilder);
					}
					
					//模糊查询  收货地址
					if (StringUtils.isNoneBlank(wayBill.getRecAddress())) {
						System.out.println("收货地址"+wayBill.getRecAddress());
						// 收货地 模糊查询
						QueryBuilder wildcardQuery = new WildcardQueryBuilder(
								"recAddress", "*" + wayBill.getRecAddress() + "*");
						query.must(wildcardQuery);
					}
					
					
					//快递类型 等值查询
					if (StringUtils.isNoneBlank(wayBill.getSendProNum())) {
						// 速运类型 等值查询
						QueryBuilder termQuery = new TermQueryBuilder("sendProNum",wayBill.getSendProNum());
						query.must(termQuery);
					}
					
					//前台默认提交的wayBill.getSignStatus()是0，但是索引库中的订单状态码为null，所以注意这里是&&。
					//如果是||name就一直会进来，然后携带条件SignStatus=0，一致查不到  
					if (wayBill.getSignStatus() != null && wayBill.getSignStatus() != 0) {
						// 签收状态查询
						QueryBuilder termQuery = new TermQueryBuilder("signStatus",wayBill.getSignStatus());
						query.must(termQuery);
					}
					//将组合条件查询传入NativeSearchQuery
					SearchQuery searchQuery = new NativeSearchQuery(query);
					Pageable pageable = new PageRequest(0, 1000);
					searchQuery.setPageable(pageable); // 分页效果
					// 有条件查询 、查询索引库
					System.out.println("查询索引库"+searchQuery.toString());
					return wayBillIndexRepository.search(searchQuery).getContent();
				}
	}


 
	
	
	
	
	

}
